package com.hxzy.common.security;


import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.hxzy.common.annon.RequiresLogin;
import com.hxzy.common.annon.RequiresPermissions;
import com.hxzy.common.annon.RequiresRoles;
import com.hxzy.common.enums.AckCode;
import com.hxzy.common.exception.ServiceException;
import com.hxzy.common.security.AdminInfoUtil;
import com.hxzy.common.security.TokenService;
import com.hxzy.system.vo.AdminLoginVO;
import org.springframework.stereotype.Component;
import org.springframework.util.PatternMatchUtils;

import java.util.Collection;
import java.util.Set;

/**
 * Token 权限验证，逻辑实现类
 * 
 * @author
 */
@Component
public class AuthLogic
{
    /** 所有权限标识 */
    private static final String ALL_PERMISSION = "*:*:*";

    /** 管理员角色权限标识 */
    private static final String SUPER_ADMIN = "admin";

    public TokenService tokenService = SpringUtil.getBean(TokenService.class);

    /**
     * 会话注销
     */
    public void logout()
    {
        String token = AdminInfoUtil.getToken();
        if (token == null)
        {
            return;
        }
        logoutByToken(token);
    }

    /**
     * 会话注销，根据指定Token
     */
    public void logoutByToken(String token)
    {
        tokenService.delLoginUser(token);
    }

    /**
     * 检验用户是否已经登录，如未登录，则抛出异常
     */
    public void checkLogin()
    {
        getLoginUser();
    }

    /**
     * 获取当前用户缓存信息, 如果未登录，则抛出异常
     * 
     * @return 用户缓存信息
     */
    public AdminLoginVO getLoginUser()
    {
        String token = AdminInfoUtil.getToken();
        if (token == null)
        {
            throw new ServiceException(AckCode.TOKEN_NOT_NULL);
        }
        AdminLoginVO loginUser = AdminInfoUtil.getAdmin();
        if (loginUser == null)
        {
            throw new ServiceException(AckCode.APPLE_ILLEGAL);
        }
        return loginUser;
    }

    /**
     * 获取当前用户缓存信息, 如果未登录，则抛出异常
     * 
     * @param token 前端传递的认证信息
     * @return 用户缓存信息
     */
    public AdminLoginVO getLoginUser(String token)
    {
        return tokenService.validatorToken(token);
    }


    /**
     * 验证用户是否具备某权限
     * 
     * @param permission 权限字符串
     * @return 用户是否具备某权限
     */
    public boolean hasPermi(String permission)
    {
        return hasAuthority(getPermiList(), permission);
    }





    /**
     * 判断用户是否拥有某个角色
     * 
     * @param role 角色标识
     * @return 用户是否具备某角色
     */
    public boolean hasRole(String role)
    {
        return hasRole(getRoleList(), role);
    }

    /**
     * 判断用户是否拥有某个角色, 如果验证未通过，则抛出异常: NotRoleException
     * 
     * @param role 角色标识
     */
    public void checkRole(String role)
    {
        if (!hasRole(role))
        {
            throw new ServiceException(AckCode.PERMISSION_NOT_ACCESS);
        }
    }

    /**
     * 根据注解(@RequiresRoles)鉴权
     *
     * @param requiresRoles 注解对象
     */
    public void checkRole(RequiresRoles requiresRoles)
    {
        Set<String> roleList = getRoleList();
        for (String role : requiresRoles.value())
        {
            if (!hasRole(roleList, role))
            {
                throw new ServiceException(AckCode.PERMISSION_NOT_ACCESS);
            }
        }
    }
    /**
     * 根据注解(@RequiresPermissions)鉴权
     *
     * @param requiresPermissions 注解对象
     */
    public void checkPermissions(RequiresPermissions requiresPermissions) {
        Set<String> permiList = getPermiList();
        if (!hasAuthority(permiList, requiresPermissions.value())) {
            throw new ServiceException(AckCode.PERMISSION_NOT_ACCESS);
        }
    }



    /**
     * 根据注解(@RequiresLogin)鉴权
     * 
     * @param at 注解对象
     */
    public void checkByAnnotation(RequiresLogin at)
    {
        this.checkLogin();
    }



    /**
     * 获取当前账号的角色列表
     * 
     * @return 角色列表
     */
    public Set<String> getRoleList()
    {
        AdminLoginVO loginUser = getLoginUser();
        return loginUser.getRoleSet();

    }

    /**
     * 获取当前账号的权限列表
     * 
     * @return 权限列表
     */
    public Set<String> getPermiList()
    {
        AdminLoginVO loginUser = getLoginUser();
       return loginUser.getPermsSet();

    }

    /**
     * 判断是否包含权限(商家或管理员)
     * 
     * @param authorities 权限列表
     * @param permission 权限字符串
     * @return 用户是否具备某权限
     */
    public boolean hasAuthority(Collection<String> authorities, String permission)
    {
        return authorities.stream().filter(p->StrUtil.isNotBlank(p))
                .anyMatch(x -> ALL_PERMISSION.contains(x) || PatternMatchUtils.simpleMatch(x, permission));
    }


    /**
     * 判断是否包含角色
     * 
     * @param roles 角色列表
     * @param role 角色
     * @return 用户是否具备某角色权限
     */
    public boolean hasRole(Collection<String> roles, String role)
    {
        return roles.stream().filter(p->StrUtil.isNotBlank(p))
                .anyMatch(x -> SUPER_ADMIN.contains(x) || PatternMatchUtils.simpleMatch(x, role));
    }
}
